package com.yhy.wxzn.wms.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.yhy.wxzn.common.enums.*;
import com.yhy.wxzn.common.exception.WmsBusinessException;
import com.yhy.wxzn.common.service.IWmsBusinessService;
import com.yhy.wxzn.common.utils.DateUtil;
import com.yhy.wxzn.common.utils.ObjectFilterHelper;
import com.yhy.wxzn.wcs.device.rgv.enums.NodeStatus;
import com.yhy.wxzn.wcs.device.rgv.enums.NodeType;
import com.yhy.wxzn.wcs.entity.*;
import com.yhy.wxzn.wcs.service.*;
import com.yhy.wxzn.wms.entity.*;
import com.yhy.wxzn.wms.mapper.WmsAsnMapper;
import com.yhy.wxzn.wms.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 收货单
 * @Author: jeecg-boot
 * @Date: 2023-10-31
 * @Version: V1.0
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class WmsAsnServiceImpl extends ServiceImpl<WmsAsnMapper, WmsAsn> implements IWmsAsnService {
    @Autowired
    private WmsAsnMapper asnMapper;
    @Autowired
    private IWmsBusinessService businessService;
    @Autowired
    private IWmsAsnDetailService asnDetailService;
    @Autowired
    private IWcsMapInfoService mapInfoService;
    @Autowired
    private IWmsPutAwayTaskService putAwayTaskService;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private IWmsAsyncMsgService asyncMsgService;
    @Autowired
    private IWmsBusinessMsgService businessMsgService;
    @Autowired
    private IWmsInboundConfigService inboundConfigService;

    @Override
    public IPage<WmsAsn> pageSelf(Page<WmsAsn> page, QueryWrapper<WmsAsn> queryWrapper) {
        return asnMapper.pageSelf(page, queryWrapper);
    }

    @Override
    public void addAsn(WmsAsn wmsAsn) {
        String asnCode = businessService.genWmsBusinessCode("ASN" + DateUtil.format(new Date(), "YYMMdd"), 8);
        wmsAsn.setCode(asnCode);
        if (StringUtils.isEmpty(wmsAsn.getOrderDate())) {
            wmsAsn.setOrderDate(new Date());
        }
        ObjectFilterHelper.getObjDefault(wmsAsn);
        this.save(wmsAsn);
    }

    @Override
    public void allocateBatch(String asnIds) {
        List<String> asnList = Arrays.asList(asnIds.split(","));
        StringBuffer msgBuffer = new StringBuffer();
        asnList = filterAsnStatus(asnList, "ALLOCATE", Arrays.asList(WmsOrderStatusEnums.SHWC.getValue(), WmsOrderStatusEnums.BFSH.getValue()), Arrays.asList(WmsOrderStatusEnums.XJ.getValue(), WmsOrderStatusEnums.BFFP.getValue()));
        Set<WmsAsn> setQueue = new HashSet<>();
        asnList.stream().forEach(a -> {
            WmsAsn asn = this.getById(a);
            try {
                if (!setQueue.contains(asn)) {
                    this.allocate(asn);
                }
            } catch (Exception e) {
                setQueue.add(asn);
                msgBuffer.append("单号:【" + asn.getCode() + "】分配失败:" + e.getMessage());
            }
        });
        if (!ObjectUtils.isEmpty(msgBuffer)) {
            //发送处理失败消息
            sendFailMessage(msgBuffer.toString(), "ALLOCATE");
        }
    }

    private void sendFailMessage(String errorMsg, String msgType) {
        //获取当前登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        MessageDTO msgDto = new MessageDTO();
        msgDto.setFromUser(user.getUsername());
        msgDto.setToUser(user.getUsername());
        msgDto.setContent(errorMsg);
        if ("ALLOCATE".equals(msgType)) {
            msgDto.setTitle("上架分配失败消息");
        } else {
            msgDto.setTitle("上架分发失败消息");
        }
        sysBaseAPI.sendSysAnnouncement(msgDto);
    }

    private void allocate(WmsAsn asn) {
        log.info("================开始分配ASN单：【" + asn.getCode() + "】==========================");
        LambdaQueryWrapper<WmsAsnDetail> detailQuery = new LambdaQueryWrapper<>();
        detailQuery.eq(WmsAsnDetail::getAsnId, asn.getId());
        detailQuery.eq(WmsAsnDetail::getDetailStatus, WmsOrderStatusEnums.YSH.getValue());
        detailQuery.eq(WmsAsnDetail::getAllocateStatus, WmsOrderStatusEnums.XJ.getValue());
        /**
         * 查询，入库单据detail中，过账状态为已收货、分配状态为新建的数据
         */
        List<WmsAsnDetail> details = asnDetailService.list(detailQuery);




        //genPutAwayTask(asn, coord, asnDetails, pallet);
    }

    private void genPutAwayTask(WmsAsn asn, WcsMapInfo coord, List<WmsAsnDetail> asnDetails, String pallet) {
        WcsMapInfo source = mapInfoService.getById(asn.getReceiveLocationId());
        BigDecimal receivedQty = asnDetails.stream().map(WmsAsnDetail::getReceivedQty).reduce(BigDecimal.ZERO, BigDecimal::add);
        WmsPutAwayTask task = new WmsPutAwayTask();
        String taskNo = businessService.genWmsBusinessCode("AT" + DateUtil.format(new Date(), "YYMMdd"), 8);
        task.setTaskNo(taskNo);
        task.setAsnCode(asn.getCode());
        task.setSource(source.getCoord());
        task.setTarget(coord.getCoord());
        task.setTaskQty(receivedQty);
        task.setContainerNo(pallet);
        ObjectFilterHelper.getObjDefault(task);
        putAwayTaskService.save(task);
        asnDetails.stream().forEach(a -> {
            a.setAllocateQty(a.getDemonQty());
        });
        mapInfoService.saveOrUpdate(coord);
        asnDetailService.saveOrUpdateBatch(asnDetails);
        asnDetailService.refreshAsnStatus(asn.getId());
        //自动分发
//        JSONObject jsonMsg = new JSONObject();
//        jsonMsg.put("businessCode", WmsMsgTypeEnums.MSG2.getCode());
//        jsonMsg.put("relateBusinessId", asn.getId());
//        asyncMsgService.genAsyncMsg(JSONObject.toJSONString(jsonMsg), WmsMsgTypeEnums.MSG2.getCode(), asn.getCode());
    }

    private List<String> filterAsnStatus(List<String> asnIds, String searchType, List<Integer> asnStatus, List<Integer> otherStatus) {
        StringBuffer sql = new StringBuffer();
        if ("ALLOCATE".equals(searchType)) {
            sql.append("select id from wms_asn where asn_status in {0} and allocate_status in {1} and id in {2}");
        } else {
            sql.append("select id from wms_asn where allocate_status in {0} and put_away_status in {1} and id in {2}");
        }
        List<Map<String, Object>> mapList = SqlRunner.db().selectList(sql.toString(), asnStatus, otherStatus, asnIds);
        if (CollectionUtils.isEmpty(mapList)) {
            throw new WmsBusinessException("未匹配到符合条件的ASN单!");
        }
        List<String> result = mapList.stream().map(m -> m.get("id") + "").collect(Collectors.toList());
        return result;
    }

    @Override
    public void dispatchBatch(String asnIds) {
        List<String> asnList = Arrays.asList(asnIds.split(","));
        StringBuffer msgBuffer = new StringBuffer();
        asnList = filterAsnStatus(asnList, "DISPATCH", Arrays.asList(WmsOrderStatusEnums.BFFP.getValue(), WmsOrderStatusEnums.FPWC.getValue()), Arrays.asList(WmsOrderStatusEnums.XJ.getValue(), WmsOrderStatusEnums.BFSJ.getValue()));
        Set<WmsAsn> setQueue = new HashSet<>();
        asnList.stream().forEach(a -> {
            WmsAsn asn = this.getById(a);
            try {
                if (!setQueue.contains(asn)) {
                    this.dispatch(asn);
                }
            } catch (Exception e) {
                setQueue.add(asn);
                msgBuffer.append("单号:【" + asn.getCode() + "】分发失败:" + e.getMessage());
            }
        });
        if (!ObjectUtils.isEmpty(msgBuffer)) {
            //发送处理失败消息
            sendFailMessage(msgBuffer.toString(), "DISPATCH");
        }
    }

    private void dispatch(WmsAsn asn) {
        log.info("================开始分发ASN单：【" + asn.getCode() + "】==========================");
        businessMsgService.dispatchPutAwayTask(asn);
    }
}
